package cqrtplm.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hustcad.plm.pdm.partbom.service.partalternate.TyplmPdmPartAlternateService;
import com.hustcad.plm.pdm.partbom.vo.AlternateInfoVO;
import cqrtplm.dto.DspfStatusModuleitemDTO;
import cqrtplm.dto.RtCfgTemplatecontentConstraintsDTO;
import cqrtplm.entity.DspfStatusModuleitemDO;
import cqrtplm.entity.DspfStatusModuleitemsubDO;
import cqrtplm.mapper.DspfStatusModuleitemMapper;
import cqrtplm.mapper.DspfStatusModuleitemsubMapper;
import cqrtplm.mapper.RtCfgStatusInfoMapper;
import cqrtplm.vo.ModelAndProductTypeVO;
import cqrtplm.vo.ModuleitemTreeVO;
import cqrtplm.vo.StatusSubTreeVO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.expression.Expression;
import com.hustcad.plm.pdm.file.handler.response.ResponseResult;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.service.snow.SnowflakeIdComponent;
import com.ty.basic.session.TyAccountContext;
import cqrtplm.entity.RtCfgTemplatecontentConstraintsDO;
import cqrtplm.mapper.RtCfgTemplatecontentConstraintsMapper;
import cqrtplm.service.RtCfgTemplatecontentConstraintsService;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

import static cqrtplm.constant.RTTableTypeConstant.TYPE_STATUS_INFO_PARTTYPE;


/**
* @author 博
* @description 针对表【RT_CFG_TEMPLATECONTENT_CONSTRAINTS(需求状态内容- 选项规则 - 约束表)】的数据库操作Service实现
* @createDate 2025-07-10 14:01:08
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class RtCfgTemplatecontentConstraintsServiceImpl extends ServiceImpl<RtCfgTemplatecontentConstraintsMapper, RtCfgTemplatecontentConstraintsDO>
    implements RtCfgTemplatecontentConstraintsService {
    @Resource
    private RtCfgTemplatecontentConstraintsMapper rtCfgTemplatecontentConstraintsMapper;
    @Resource
    private SnowflakeIdComponent snowflakeIdComponent;
    @Value("${STATUS_INFO_PARTTYPE}")
    private String STATUS_INFO_PARTTYPE;
    @Value("${STATUS_INFO_DEVCODE}")
    private String STATUS_INFO_DEVCODE;
    @Resource
    private DspfStatusModuleitemServiceImpl dspfStatusModuleitemServiceImpl;
    @Resource
    private DspfStatusModuleitemMapper dspfStatusModuleitemMapper;
    @Resource
    private DspfStatusModuleitemsubMapper dspfStatusModuleitemsubMapper;
    @Resource
    private RtCfgStatusInfoMapper rtCfgStatusInfoMapper;
    @Resource
    private TyplmPdmPartAlternateService typlmPartAlternateService;



    @Override
    public ResponseResult saveRtCfgTemplatecontentConstraints(
            RtCfgTemplatecontentConstraintsDO rtCfgTemplatecontentConstraintsDO) {
        try {
            // 1. 验证表达式规则
            String ruleContent = rtCfgTemplatecontentConstraintsDO.getRuleContent();
            if (StringUtils.isNotBlank(ruleContent)) {
                validateExpressionSyntax(ruleContent); // 新增的验证方法
            }

            // 2. 保存数据
            UserDO user = TyAccountContext.getUser();
            rtCfgTemplatecontentConstraintsDO.setId(snowflakeIdComponent.getInstance().nextId());
            rtCfgTemplatecontentConstraintsDO.setCreateUserid(user.getOid());
            rtCfgTemplatecontentConstraintsDO.setCreateUsername(user.getName());
            rtCfgTemplatecontentConstraintsDO.setCreateDate(new Date());
            rtCfgTemplatecontentConstraintsDO.setDeleteflag(new BigInteger("0"));

            int i = rtCfgTemplatecontentConstraintsMapper.insertRtCfgTemplatecontentConstraints(
                    rtCfgTemplatecontentConstraintsDO);
            return i > 0 ? ResponseResult.success("保存成功") : ResponseResult.fail("","500","保存失败");
        } catch (IllegalArgumentException e) {
            // 表达式验证失败
            return ResponseResult.fail("", "400", "表达式规则无效: " + e.getMessage());
        } catch (Exception e) {
            log.error("保存失败", e);
            return ResponseResult.fail("", "500", "保存失败");
        }
    }


    /**
     * 验证表达式语法是否合法
     */
    private void validateExpressionSyntax(String expression) {
        try {
            ExpressionParser parser = new SpelExpressionParser();
            parser.parseExpression(expression);
        } catch (Exception e) {
            throw new IllegalArgumentException("表达式语法错误: " + e.getMessage());
        }

        // 3. 运算符平衡检查（可选）
        checkParenthesesBalance(expression);
    }

    /**
     * 检查括号是否成对
     */
    private void checkParenthesesBalance(String expr) {
        int balance = 0;
        for (char c : expr.toCharArray()) {
            if (c == '(') balance++;
            if (c == ')') balance--;
            if (balance < 0) break;
        }
        if (balance != 0) {
            throw new IllegalArgumentException("括号不匹配");
        }
    }




    public boolean evaluateDynamicCondition(Map<String, String> context, String expression) {
        try {
            // 直接使用原始表达式
            ExpressionParser parser = new SpelExpressionParser();

            // 创建包含所有变量的评估上下文
            StandardEvaluationContext evalContext = new StandardEvaluationContext();
            context.forEach(evalContext::setVariable);

            // 添加根对象用于安全访问
            evalContext.setRootObject(context);

            Expression exp = parser.parseExpression(expression);
            Boolean result = exp.getValue(evalContext, Boolean.class);

            return Boolean.TRUE.equals(result);
        } catch (Exception e) {
            throw new RuntimeException("表达式评估失败: \"" + expression + "\" - " + e.getMessage(), e);
        }
    }

    @Override
    public ResponseResult testRtCfgTemplatecontentConstraints(
            Map<String,String> map) {
        // 更清晰的表达式格式
        String expression = "((#this['716516468164'] != '红色' && #this['76516564818'] == '白色') || " +
                "(#this['76516648979'] == '外氪' || (#this['51879165646'] == '随机' && #this['657865616994'] == '50')))";
        // 使用 #this 访问根对象
//        String expression = "#this['716516468164'] == '红色' && #this['76516564818'] == '白色'";

        try {
            boolean result = evaluateDynamicCondition(map, expression);
            return ResponseResult.success(result, "200");
        } catch (Exception e) {
            log.error("评估失败", e);
            return ResponseResult.fail("", "500", "评估失败: " + e.getMessage());
        }
    }

    @Override
    public ResponseResult getRtCfgStatusSubTree(ModelAndProductTypeVO modelAndProductTypeVO) throws ParseException {
        modelAndProductTypeVO.setType(TYPE_STATUS_INFO_PARTTYPE);

        // 提取 productType 和 devCode 到局部变量以提升可读性
        String productType = modelAndProductTypeVO.getProductType();
        String devCode = modelAndProductTypeVO.getDevCode();

        // 检查是否满足任一查询条件
        boolean hasProductType = StringUtils.isNotBlank(productType);
        boolean hasDevCode = StringUtils.isNotBlank(devCode);

        if (!hasProductType && !hasDevCode) {
            return ResponseResult.fail("", "500", "产品型号和设备编码均为空！");
        }

        // 统一调用 mapper 获取 objectNumber
        String objectNumber = rtCfgStatusInfoMapper.selectMoudleByProductType(
                STATUS_INFO_PARTTYPE,
                hasProductType ? productType : null, // 确保无效参数不会干扰查询
                STATUS_INFO_DEVCODE,
                devCode
        );

        if (StringUtils.isBlank(objectNumber)) {
            return ResponseResult.fail("", "500", "未查询到机型！");
        }

        List<String> alternateForPartNumbers = Collections.singletonList(objectNumber);
        List<AlternateInfoVO> alternateInfoVOS = typlmPartAlternateService.batchQueryAlternates(alternateForPartNumbers);

        if (CollectionUtils.isEmpty(alternateInfoVOS)) {
            return ResponseResult.fail("", "500", "未找到替代件信息！");
        }

        // 获取第一个 AlternateObjectMasterOid 并确保其存在
        BigInteger masterOidValue = alternateInfoVOS.stream()
                .findFirst()
                .map(AlternateInfoVO::getAlternateObjectMasterOid)
                .orElse(null);

        if (masterOidValue == null) {
            return ResponseResult.fail("", "500", "主对象 OID 不存在！");
        }

        String masterOid = String.valueOf(masterOidValue);

        if (masterOid == null || masterOid.isEmpty()){
            return ResponseResult.fail("", "500", "未找到对应的零件，请检查输入的机型!");
        }
        DspfStatusModuleitemDTO dspfStatusModuleitemDTO = new DspfStatusModuleitemDTO();
        dspfStatusModuleitemDTO.setModuleId(masterOid);
        List<DspfStatusModuleitemDO> dspfStatusModuleitemList = dspfStatusModuleitemMapper.selectByMoudleId(
                dspfStatusModuleitemDTO);
        if (dspfStatusModuleitemList == null || dspfStatusModuleitemList.isEmpty()){
            return ResponseResult.fail("", "500", "该机型未绑定模板，请先绑定模板!");
        }
        List<String> itemIds = dspfStatusModuleitemList.stream()
                .filter(dspfStatusModuleitemDO -> dspfStatusModuleitemDO.getItemType() == 1)
                .map(DspfStatusModuleitemDO::getItemId)
                .collect(Collectors.toList());
        List<DspfStatusModuleitemsubDO> dspfStatusModuleitemsubDOS = dspfStatusModuleitemsubMapper.selectbatchItemID(
                itemIds);
        List<StatusSubTreeVO> voList = new ArrayList<>();
        for (DspfStatusModuleitemDO doObj : dspfStatusModuleitemList) {
            StatusSubTreeVO vo = new StatusSubTreeVO();
            vo.setId(doObj.getItemId());
            vo.setParentId(doObj.getParentId());
            vo.setLvl(doObj.getLvl());
            vo.setName(doObj.getItemName());
            voList.add(vo);
        }
        for (DspfStatusModuleitemsubDO doObj : dspfStatusModuleitemsubDOS) {
            StatusSubTreeVO vo = new StatusSubTreeVO();
            vo.setParentId(doObj.getItemId());
            vo.setId(doObj.getSid());
            vo.setName(doObj.getDescrName());
            vo.setLvl(3);
            voList.add(vo);
        }

        Map<String, List<StatusSubTreeVO>> map = voList.stream()
                .collect(Collectors.groupingBy(StatusSubTreeVO::getParentId));

        List<StatusSubTreeVO> moduleitemTreeVOS = buildTree(map, "-1", dspfStatusModuleitemList);
        return ResponseResult.success(moduleitemTreeVOS,"");
    }

    @Override
    public ResponseResult removeRtCfgTemplatecontentConstraints(BigInteger[] ids) {
        if (ids == null || ids.length == 0) {
            return ResponseResult.fail("","500", "传入的ids为空");
        }

        // 获取当前用户信息
        UserDO user = TyAccountContext.getUser();
        Date deleteTime = new Date();

        // 创建参数Map
        Map<String, Object> params = new HashMap<>();
        params.put("deleteUserid", user.getOid());
        params.put("deleteUsername", user.getName());
        params.put("deleteDate", deleteTime);

        int i = rtCfgTemplatecontentConstraintsMapper.removeRtCfgTemplatecontentConstraints(params,ids);
        if (i <= 0) {
            return ResponseResult.fail("","500", "删除失败");
        }
        return ResponseResult.success("删除成功");
    }

    @Override
    public ResponseResult getRtCfgTemplatecontentConstraints(
            RtCfgTemplatecontentConstraintsDTO rtCfgTemplatecontentConstraintsDTO) {
        // 参数校验
        if (rtCfgTemplatecontentConstraintsDTO == null) {
            return ResponseResult.fail("","500","参数不能为空");
        }

        // 分页参数校验
        int pageNum = Math.max(1, rtCfgTemplatecontentConstraintsDTO.getPageNum());
        int pageSize = rtCfgTemplatecontentConstraintsDTO.getPageSize();
        pageSize = Math.max(1, Math.min(pageSize, 200)); // 限制最大页大小

        try {
            // 开启分页
            PageHelper.startPage(pageNum, pageSize);

            // 原查询逻辑不变
            List<RtCfgTemplatecontentConstraintsDO> list =
                    rtCfgTemplatecontentConstraintsMapper.getRtCfgTemplatecontentConstraints(
                            rtCfgTemplatecontentConstraintsDTO);

            // 封装分页结果
            PageInfo<RtCfgTemplatecontentConstraintsDO> pageInfo = new PageInfo<>(list);

            return ResponseResult.success(pageInfo, "");
        } catch (Exception e) {
            // 记录日志
            log.error("获取模板内容约束失败", e);
            return ResponseResult.fail("","500","查询失败");
        }
    }

    @Override
    public ResponseResult updateRtCfgTemplatecontentConstraints(
            RtCfgTemplatecontentConstraintsDO rtCfgTemplatecontentConstraintsDO) {
        try {
            // 1. 验证表达式规则
            String ruleContent = rtCfgTemplatecontentConstraintsDO.getRuleContent();
            if (StringUtils.isNotBlank(ruleContent)) {
                validateExpressionSyntax(ruleContent); // 新增的验证方法
            }
        } catch (IllegalArgumentException e) {
            // 表达式验证失败
            return ResponseResult.fail("", "400", "表达式规则无效: " + e.getMessage());
        }
        // 获取当前用户信息
        UserDO user = TyAccountContext.getUser();
        rtCfgTemplatecontentConstraintsDO.setModifyDate(new Date());
        rtCfgTemplatecontentConstraintsDO.setModifyUserid(user.getOid());
        rtCfgTemplatecontentConstraintsDO.setModifyUsername(user.getName());
        int i = rtCfgTemplatecontentConstraintsMapper.updateRtCfgTemplatecontentConstraints(
                rtCfgTemplatecontentConstraintsDO);
        if (i <= 0){
            return ResponseResult.fail("","500", "更新失败");
        }
        return ResponseResult.success("");
    }



    private List<StatusSubTreeVO> buildTree(Map<String, List<StatusSubTreeVO>> map, String parentId, List<DspfStatusModuleitemDO> dos){
        List<StatusSubTreeVO> children = map.getOrDefault(parentId, Collections.emptyList());

        for (StatusSubTreeVO child : children) {
            child.setChildren(buildTree(map, child.getId(), dos));
        }
        return children;
    }
}

